import React from 'react';
//import './App.css';
import { Button } from 'antd';
import { CaretUpOutlined, CaretLeftOutlined, CaretRightOutlined, CaretDownOutlined } from '@ant-design/icons';
import "./game.scss";
import "antd/dist/antd.css";
import AI from "./ai/ai.js"

var ai = new AI()

const /**
   * 五子棋行数
   */
  ROW_COUNT = 15,
  /**
   * 五子棋列数
   */
  COL_COUNT = 15,
  /**
   * 值对应的显示文本
   */
  VALUE_TEXT = {
    0: "",
    1: "♘",
    2: "♞"
  };


/**
* 创建原始数据
*/
function crateGridArr(row, col) {
  let outData = [],
    rowData = [];

  for (let i = 0; i < col; i++) {
    rowData.push(0);
  }
  for (let i = 0; i < row; i++) {
    outData.push(rowData.concat());
  }

  return outData;
}



/**
 * 棋子单元格
 */
function Square(props) {
  return (
    <label
      className={`square ${props.active ? "active" : ""} ${props.chosed ? "chosed" : ""}`}
      datarow={props.row}
      datacol={props.col}
    >
      {VALUE_TEXT[props.value]}
    </label>
  );
}




/**
 * 五子棋
 */
class Gomoku extends React.Component {
  constructor() {
    super();

    // 生成15X15的网格数据，O:1，X:2
    this.state = {
      grid: crateGridArr(ROW_COUNT, COL_COUNT)
    };

    this.curUser = 2;
    this.gameOver = false;
    this.isPeace = false;
    this.result = [];

    this.chosedX = 7;
    this.chosedY = 7;

    ai.start(false)
    console.log('ai.start')

    //this.x=0;

  }

  IsPeace(data) {
    for (let i = 0; i < 15; i++) {
      for (let j = 0; j < 15; j++) {
        if (data[i][j] == 0) {
          return false
        }
      }
    }
    return true;

  }


  AItodo(x, y) {

    if (this.gameOver) {
      return;
    }


    let data = this.state.grid.concat();

    //是否平局
    if (this.IsPeace(data)) {
      this.gameOver = true;
      this.isPeace = true;
      this.setState({});
      return;
    }


    var p = ai.turn(x, y);
    console.log('ai.turn')
    console.log(p)


    const row = p[0];
    const col = p[1];

    // this.x=this.x+2
    // let row = this.x;
    // let col = this.x;


    data[row][col] = this.curUser;

    let result = checkWin(data, row, col);

    this.setStaticState(result, 2);

    this.setState({
      grid: data
    });

    this.chosedX = row;
    this.chosedY = col;


  }

  putDot(row,col){

    if (this.state.grid[row][col] !== 0) {
      console.log("当前单元格已被使用.");
      return;
    }


    let data = this.state.grid.concat();
    data[row][col] = this.curUser;

    let result = checkWin(data, row, col);

    this.setStaticState(result, 1);

    this.setState({
      grid: data
    }, () => {
      this.AItodo(row, col);
    })
  }

  /**
   * 下棋
   */
  handleClick(e) {
    //console.log(e.target)
    let target = e.target;
    if (this.gameOver || !target.getAttribute("datarow")) {
      return;
    }

    let row = +target.getAttribute("datarow"),
      col = +target.getAttribute("datacol");

    this.putDot(row,col)

  }



  setCurUser(user) {
    if (user) {
      this.curUser = user;
      return;
    }
    this.curUser = this.curUser === 1 ? 2 : 1;
  }


  //TODO
  setStaticState(result, user) {
    this.result = [];
    if (result && result.length === 5) {
      this.gameOver = true;
      result.forEach(item => {
        this.result.push(`${item.x}-${item.y}`);
      });
    } else {
      this.gameOver = false;
    }
    this.setCurUser(user);
  }




  reSet() {

    this.setStaticState([], 2);

    this.setState({
      grid: crateGridArr(ROW_COUNT, COL_COUNT)
    });

    this.gameOver = false;
    this.isPeace = false;

    this.chosedX = 7;
    this.chosedY = 7;

    ai.start(false)
    console.log('ai.start')

  }

  reBack() {

    const res = ai.backward()

    console.log('ai.backward')
    //console.log(res)
    this.setState({
      grid: res,
    });
    this.gameOver = false;
    this.isPeace = false;
    
    //this.chosedX = 7;
    //this.chosedY = 7;
  }


  changeBox(dir) {
      switch (dir) {
        case '上':
          if (this.chosedX > 0 ) {
            this.chosedX = this.chosedX - 1;
          }
          break;
        case '下':
          if (this.chosedX < 14) {
            this.chosedX = this.chosedX + 1;
          }
          break;
        case '左':
          if (this.chosedY > 0 ) {
            this.chosedY = this.chosedY - 1;
          }
          break;
        case '右':
          if (this.chosedY < 14) {
            this.chosedY = this.chosedY + 1;
          }
          break;
        default:
          break;
      }
      this.setState({});
  }


  render() {

    // let text = this.gameOver
    //   ? `Winner: ${VALUE_TEXT[this.curUser === 1 ? 2 : 1]}`
    //   : `玩家使用: ${VALUE_TEXT[this.curUser]}`;

    let text = '';
    if (this.gameOver) {
      if (this.isPeace) {
        text = '--- 平 局 ---'
      } else {
        text = this.curUser === 1 ? '玩家获胜' : '电脑获胜'
      }
    } else {
      text = `玩家使用: ${VALUE_TEXT[this.curUser]}`;
    }

    return (
      <div className="gomoku-box" onClick={e => this.handleClick(e)}>


        <div className="msg">
          <label >{text}</label>
        </div>


        <div className="square-box">
          {this.state.grid.map((row, i) => {
            return (
              <div key={i} className="square-row">
                {row.map((cell, j) => {
                  let key = `${i}-${j}`;
                  return (
                    <Square
                      key={key}
                      active={this.gameOver && this.result.includes(key)}
                      value={cell}
                      row={i}
                      col={j}
                      chosed={i == this.chosedX && j == this.chosedY}
                    />
                  );
                })}
              </div>
            );
          })}
        </div>


        <div className="gomoku-bar">
          <button onClick={() => this.reSet()}>重新开始</button>
          <button onClick={() => this.reBack()}>悔棋</button>
        </div>



        <div className="btn-bar">
          <Button type="primary" icon={<CaretUpOutlined />} onClick={() => this.changeBox('上')} />
        </div>
        <div className="btn-bar">
          <Button type="primary" icon={<CaretLeftOutlined />} onClick={() => this.changeBox('左')} />
          <button onClick={() => this.putDot(this.chosedX,this.chosedY)}>确认</button>
          <Button type="primary" icon={<CaretRightOutlined />} onClick={() => this.changeBox('右')} />
        </div>
        <div className="btn-bar">
          <Button type="primary" icon={<CaretDownOutlined />} onClick={() => this.changeBox('下')} />
        </div>


      </div>
    );
  }
}

export default Gomoku;


const direction = {
  horizontal: 1,
  vertical: 2,
  leftOblique: 3,
  rightOblique: 4
};

/**
 * 判断当前游戏是否结束
 * @param {Array} arr
 * @param {Number} x 当前棋子的横坐标
 * @param {Number} y 当前棋子的纵坐标
 * 赢的情况
 * 连续的五个棋子相同
 * 横线，竖线，左斜线，右斜线四种情况
 */
function checkWin(arr, x, y) {
  let target = arr[x][y],
    rowLen = arr.length,
    colLen = arr[0].length,
    startNode = { x, y },
    nodeList;

  function check(node) {
    if (node.x >= rowLen || node.x < 0 || node.y >= colLen || node.y < 0) {
      return false;
    }
    if (arr[node.x][node.y] === target) {
      return true;
    }
    return false;
  }

  for (let i = 1; i <= 4; i++) {
    nodeList = [startNode];
    let left = startNode,
      right = startNode,
      leftVal = true,
      rightVal = true;

    // 从当前节点出发，左右或者上下同时检测
    while (leftVal || rightVal) {
      if (leftVal) {
        left = getCoordinate(i, left, -1);
        leftVal = check(left) && nodeList.push(left);
      }
      if (rightVal) {
        right = getCoordinate(i, right, 1);
        rightVal = check(right) && nodeList.push(right);
      }

      if (nodeList.length === 5) {
        return nodeList;
      }
    }
  }
  return nodeList;
}

function getCoordinate(direct, node, tag) {
  let newNode;
  switch (direct) {
    case direction.horizontal:
      newNode = {
        x: node.x,
        y: node.y + tag
      };
      break;
    case direction.vertical:
      newNode = {
        x: node.x + tag,
        y: node.y
      };
      break;
    case direction.leftOblique:
      newNode = {
        x: node.x + tag,
        y: node.y + tag
      };
      break;
    case direction.rightOblique:
      newNode = {
        x: node.x - tag,
        y: node.y + tag
      };
      break;
    default:
      newNode = {
        x: -1,
        y: -1
      };
  }
  return newNode;
}
